import requests
import json
from typing import List, Dict, Any
import base64
import urllib.parse
from dotenv import load_dotenv
import os

# 加载环境变量
load_dotenv()

class FeishuTableHandler:
    def __init__(self, app_id: str, app_secret: str):
        """
        初始化飞书表格处理器
        :param app_id: 飞书应用的App ID
        :param app_secret: 飞书应用的App Secret
        """
        self.app_id = app_id
        self.app_secret = app_secret
        self.access_token = None
    
    def get_access_token(self) -> str:
        """获取飞书访问令牌"""
        url = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal"
        payload = {
            "app_id": self.app_id,
            "app_secret": self.app_secret
        }
        headers = {
            "Content-Type": "application/json"
        }
        
        response = requests.post(url, data=json.dumps(payload), headers=headers)
        result = response.json()
        
        if result.get("code") == 0:
            self.access_token = result.get("tenant_access_token")
            return self.access_token
        else:
            raise Exception(f"获取飞书访问令牌失败: {result}")
    
    def get_sheet_data(self, sheet_token: str, sheet_name: str) -> List[Dict[str, Any]]:
        """
        获取飞书表格数据
        :param sheet_token: 表格文档的token
        :param sheet_name: 表格名称
        :return: 表格数据列表
        """
        if not self.access_token:
            self.get_access_token()
        
        url = f"https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/{sheet_token}/values/{sheet_name}"
        headers = {
            "Authorization": f"Bearer {self.access_token}",
            "Content-Type": "application/json"
        }
        
        response = requests.get(url, headers=headers)
        result = response.json()
        
        if result.get("code") == 0:
            values = result.get("data", {}).get("valueRange", {}).get("values", [])
            if not values:
                return []
            
            # 第一行作为表头
            headers = values[0]
            data = []
            
            for row in values[1:]:
                row_data = {}
                for i, cell in enumerate(row):
                    if i < len(headers):
                        row_data[headers[i]] = cell
                data.append(row_data)
            
            return data
        else:
            raise Exception(f"获取表格数据失败: {result}")


class GerritHandler:
    def __init__(self, gerrit_url: str, username: str, password: str):
        """
        初始化Gerrit处理器
        :param gerrit_url: Gerrit服务器URL
        :param username: Gerrit用户名
        :param password: Gerrit密码
        """
        self.gerrit_url = gerrit_url.rstrip('/')
        self.auth = base64.b64encode(f"{username}:{password}".encode()).decode()
    
    def create_branch(self, project_name: str, source_branch: str, target_branch: str) -> None:
        """
        使用Gerrit API创建分支
        :param project_name: 项目名称
        :param source_branch: 源分支名称
        :param target_branch: 目标分支名称
        """
        escaped_source_branch = urllib.parse.quote(source_branch, safe='')
        escaped_target_branch = urllib.parse.quote(target_branch, safe='')
        escaped_project_name = urllib.parse.quote(project_name, safe='')
        
        url = f"{self.gerrit_url}/a/projects/{escaped_project_name}/branches/{escaped_target_branch}"
        headers = {
            "Authorization": f"Basic {self.auth}",
            "Content-Type": "application/json"
        }
        
        # 获取源分支的commit ID
        ref_url = f"{self.gerrit_url}/a/projects/{escaped_project_name}/branches/{escaped_source_branch}"
        ref_response = requests.get(ref_url, headers=headers)
        if ref_response.status_code != 200:
            raise Exception(f"get {source_branch} failed: {ref_response.text}")
        
        # 处理Gerrit API返回的特殊字符")]}'"
        response_text = ref_response.text
        if response_text.startswith(")]}'"):
            response_text = response_text.replace(")]}'", "", 1)
        
        # 解析JSON
        ref_info = json.loads(response_text)
        revision = ref_info.get("revision")
        
        if not revision:
            raise Exception(f"{project_name} can not get {source_branch} revision")
        
        # 创建新分支
        payload = {
            "revision": revision
        }
        
        # 发送PUT请求创建新分支，传递headers和payload数据
        response = requests.put(url, headers=headers, data=json.dumps(payload))
        
        if response.status_code != 201:
            raise Exception(f"{project_name} create {target_branch} failed: {response.text}")


def create_branch_from_feishu(app_id: str, app_secret: str, sheet_token: str, sheet_name: str, 
                           gerrit_url: str, gerrit_username: str, gerrit_password: str) -> None:
    """
    处理飞书表格并创建分支的主函数
    :param app_id: 飞书应用的App ID
    :param app_secret: 飞书应用的App Secret
    :param sheet_token: 表格文档token
    :param sheet_name: 表格名称
    :param gerrit_url: Gerrit服务器URL
    :param gerrit_username: Gerrit用户名
    :param gerrit_password: Gerrit密码
    """
    # 初始化飞书表格处理器
    feishu_handler = FeishuTableHandler(app_id, app_secret)
    
    # 获取表格数据
    sheet_data = feishu_handler.get_sheet_data(sheet_token, sheet_name)
    
    # 初始化Gerrit处理器
    gerrit_handler = GerritHandler(gerrit_url, gerrit_username, gerrit_password)
    
    for row in sheet_data:
        gerrit_repo_url = row.get("仓库")
        source_branch = row.get("base分支")
        sop_branch = row.get("sop分支")
        
        # 检查任一字段是否为空
        if not gerrit_repo_url or not source_branch or not sop_branch:
            # print(f"跳过数据不完整的行")
            continue
        
        try:
            # 从gitlab URL中提取project_name，移除http://git.gxatek.com/前缀和.git后缀
            project_name = gerrit_repo_url[0]['text'].replace('http://git.gxatek.com/', '').replace('.git', '')
            if project_name == "" or project_name == " " or project_name == "\n":
                raise Exception(f"project_name is empty: {gerrit_repo_url}")
            
            # 使用Gerrit API创建分支
            gerrit_handler.create_branch(project_name, source_branch, sop_branch)
            
            print(f"success: {project_name} create branch {sop_branch} from {source_branch}")
        except Exception as e:
            print(f"error: {project_name} {str(e)}")


if __name__ == "__main__":
    # 从环境变量获取配置
    APP_ID = os.getenv("FEISHU_APP_ID")
    APP_SECRET = os.getenv("FEISHU_APP_SECRET")
    
    # Gerrit配置
    GERRIT_URL = os.getenv("GERRIT_URL")
    GERRIT_USERNAME = os.getenv("GERRIT_USERNAME")
    GERRIT_PASSWORD = os.getenv("GERRIT_PASSWORD")
    
    # 提取表格token和名称
    SHEET_TOKEN = os.getenv("SHEET_TOKEN")
    SHEET_NAME = os.getenv("SHEET_NAME")
    
    # 执行主流程
    create_branch_from_feishu(APP_ID, APP_SECRET, SHEET_TOKEN, SHEET_NAME, 
                           GERRIT_URL, GERRIT_USERNAME, GERRIT_PASSWORD)
